package cn.dakaqi.utils.qrcode;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import org.apache.commons.codec.binary.Base64;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.Hashtable;

/**
 * Created by chunyang on 2016/4/21.
 */
public class QRCode
{
    private final String text;
    private ImageType imageType = ImageType.PNG;
    private int width = 125;
    private int height = 125;

    private static final String CHARSET = "utf-8";
    private static final String FORMAT_NAME = "JPG";
    // 二维码尺寸
    private static final int QRCODE_SIZE = 300;
    // LOGO宽度
    private static final int WIDTH = 60;
    // LOGO高度
    private static final int HEIGHT = 60;

    private QRCode(String text) {
        this.text = text;
    }

    public static QRCode from(String text)
    {
        return new QRCode(text);
    }

    public QRCode to(ImageType imageType)
    {
        this.imageType = imageType;
        return this;
    }

    public QRCode withSize(int width, int height)
    {
        this.width = width;
        this.height = height;
        return this;
    }

    public File file()
    {
        File file;
        try
        {
            file = createTempFile();
            MatrixToImageWriter.writeToFile(createMatrix(), this.imageType.toString(), file);
        } catch (Exception e) {
            throw new QRGenerationException("Failed to create QR image from text due to underlying exception", e);
        }

        return file;
    }

    public ByteArrayOutputStream stream()
    {
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        try {
            MatrixToImageWriter.writeToStream(createMatrix(), this.imageType.toString(), stream);
        } catch (Exception e) {
            throw new QRGenerationException("Failed to create QR image from text due to underlying exception", e);
        }

        return stream;
    }
    public BufferedImage bufferedImage()
    {
        BufferedImage bufferedImage = null;
        try {

            bufferedImage = MatrixToImageWriter.toBufferedImage(createMatrix());
        } catch (Exception e) {
            throw new QRGenerationException("Failed to create QR image from text due to underlying exception", e);
        }

        return bufferedImage;
    }
    private BitMatrix createMatrix() throws WriterException
    {
        //return new QRCodeWriter().encode(this.text, BarcodeFormat.QR_CODE, this.width, this.height);
        Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
        hints.put(EncodeHintType.CHARACTER_SET, CHARSET);
        hints.put(EncodeHintType.MARGIN, 1);
        BitMatrix bitMatrix = new MultiFormatWriter().encode(this.text,BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE, hints);
        return bitMatrix;
    }

    private File createTempFile() throws IOException
    {
        File file = File.createTempFile("QRCode", "." + this.imageType.toString().toLowerCase());
        file.deleteOnExit();
        return file;
    }

    public static void main(String[] args)
    {
        test();
    }
    public static void test()
    {
        String qrtext = "张春洋";
        ByteArrayOutputStream out = QRCode.from(qrtext).to(ImageType.PNG).stream();
        byte[] data = out.toByteArray();
        System.out.println(new String(Base64.encodeBase64(data)));
    }
}
